package per.sunmes.lesrb.util;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.BitmapFont.BitmapFontData;
import com.badlogic.gdx.graphics.g2d.BitmapFont.Glyph;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.FrameBuffer;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Touchable;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Scaling;

import per.sunmes.lesrb.action.CallAction;
import per.sunmes.lesrb.actor.FrameAnimationActor;
import per.sunmes.lesrb.manager.RM;

public class U {

	public static void stageSize(Actor a) {
		a.setSize(GM.stage.getWidth(), GM.stage.getHeight());
	}

	public static void centerTo(Actor a, Actor b) {
		a.setPosition(b.getX() + b.getWidth() / 2, b.getY() + b.getHeight() / 2, Align.center);
	}

	public static void centerBy(Actor a, Actor b) {
		a.setPosition(b.getWidth() / 2, b.getHeight() / 2, Align.center);
	}

	public static void disTouch(Actor a) {
		a.setTouchable(Touchable.disabled);
	}

	public static void enTouch(Actor a) {
		a.setTouchable(Touchable.enabled);
	}

	public static Actor createActorCall(CallAction call) {
		Actor a = new Actor();
		a.addAction(Actions.sequence(call, Actions.removeActor()));
		return a;
	}

	public static Actor createActorCall(float delay, CallAction call) {
		Actor a = new Actor();
		a.addAction(Actions.sequence(Actions.delay(delay), call, Actions.removeActor()));
		return a;
	}

	public static Group groupUntransform() {
		Group g = new Group();
		g.setTransform(false);
		return g;
	}

	public static Image image(Image image) {
		return new Image(image.getDrawable());
	}

	/** 将图片按照字符序列生成BitmapFont */
	public static BitmapFont createPicFont(String name, String chars) {
		return createPicFont(name, chars, null);
	}

	/** 将图片按照字符序列生成BitmapFont */
	public static BitmapFont createPicFont(String name, String chars, TextureFilter filter) {
		TextureRegion region = region(name, filter);
		BitmapFontData data = new BitmapFontData();
		int width = region.getRegionWidth() / chars.length();
		for (int i = 0; i < chars.length(); i++) {
			Glyph g = new Glyph();
			char c = chars.charAt(i);
			g.id = c;
			g.srcX = i * width;
			g.xadvance = width;
			g.width = width;
			g.height = region.getRegionHeight();
			data.setGlyph(c, g);
		}
		BitmapFont font = new BitmapFont(data, region, false);
		return font;
	}

	/** 将图片按照字符序列生成BitmapFont */
	public static BitmapFont createPicFont(TextureRegion region, String chars) {
		BitmapFontData data = new BitmapFontData();
		int width = region.getRegionWidth() / chars.length();
		for (int i = 0; i < chars.length(); i++) {
			Glyph g = new Glyph();
			char c = chars.charAt(i);
			g.id = c;
			g.srcX = i * width;
			g.xadvance = width;
			g.width = width;
			g.height = region.getRegionHeight();
			data.setGlyph(c, g);
		}
		BitmapFont font = new BitmapFont(data, region, false);
		return font;
	}

	/**
	 * 将独立的TextureRegion按照字符序列合成FrameBuffer,再生成BitmapFont</br>
	 * 生成的FrameBuffer会被放进RM.addDispose(fbo).
	 */
	public static BitmapFont createPicFontFrameBuffer(String chars, Array<TextureRegion> regions) {
		int height = 0, width = 0;
		float off = 4;
		for (int i = 0; i < chars.length(); i++) {
			TextureRegion tr = regions.get(i);
			if (height < tr.getRegionHeight()) {
				height = tr.getRegionHeight();
			}
			width += tr.getRegionWidth() + off;
		}
		FrameBuffer fbo = new FrameBuffer(Format.RGBA8888, MathUtils.nextPowerOfTwo(width),
				MathUtils.nextPowerOfTwo(height), false);
		OrthographicCamera camera = new OrthographicCamera(fbo.getWidth(), fbo.getHeight());
		camera.translate(fbo.getWidth() / 2, fbo.getHeight() / 2);
		SpriteBatch batch = new SpriteBatch();
		fbo.getColorBufferTexture().setFilter(U.usedTextureFilter, U.usedTextureFilter);
		fbo.begin();
		Gdx.gl.glClearColor(0, 0, 0, 0);
		Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
		camera.update();
		batch.setProjectionMatrix(camera.combined);
		batch.begin();
		width = 0;
		for (int i = 0; i < regions.size; i++) {
			TextureRegion tr = regions.get(i);
			batch.draw(tr, width, tr.getRegionHeight(), tr.getRegionWidth(), -tr.getRegionHeight());
			width += tr.getRegionWidth() + off;
		}
		batch.end();
		fbo.end();
		batch.dispose();

		GM.stage.getViewport().apply();

		BitmapFontData data = new BitmapFontData();
		data.setLineHeight(height);
		data.capHeight = height;
		data.xHeight = height;
		int px = 0;
		for (int i = 0; i < chars.length(); i++) {
			width = regions.get(i).getRegionWidth();
			Glyph g = new Glyph();
			char c = chars.charAt(i);
			g.id = c;
			g.srcX = px;
			g.srcY = 0;
			g.yoffset = -regions.get(i).getRegionHeight();
			g.xadvance = width;
			g.width = width;
			g.height = regions.get(i).getRegionHeight();
			px += width + off;
			data.setGlyph(c, g);
		}
		TextureRegion region = new TextureRegion(fbo.getColorBufferTexture(), 0, 0, fbo.getWidth(), fbo.getHeight());
		BitmapFont font = new BitmapFont(data, region, false);
		RM.addDisposable(fbo);

		return font;
	}

	public static TextureFilter usedTextureFilter = TextureFilter.Nearest;

	public static TextureRegion region(String name, TextureFilter filter) {
		TextureRegion region;
		region = RM.getRegion(name);
		if (filter != null) {
			Texture t = region.getTexture();
			if (t.getMagFilter() != filter || t.getMinFilter() != filter) {
				t.setFilter(filter, filter);
			}
		}
		return region;
	}

	public static TextureRegion region(String name) {
		return region(name, usedTextureFilter);
	}

	public static TextureRegion region(String name, int x, int y, int width, int height) {
		TextureRegion region;
		region = new TextureRegion(region(name).getTexture(), x, y, width, height);
		return region;
	}

	/**
	 * 将Region按横纵数据切割，以坐下角为0-0，取指定位置切割后的区域
	 * 
	 * @param name
	 *            要切割的TextureRegion
	 * @param xCount
	 *            横轴切割数量
	 * @param yCount
	 *            纵轴切割数量
	 * @param partX
	 *            从0开始，由左至右
	 * @param partY
	 *            从0开始，由下至上
	 * @return
	 */
	public static TextureRegion regionChild(TextureRegion src, int xCount, int yCount, int partX, int partY) {
		int childWidth = src.getRegionWidth() / xCount;
		int childHeight = src.getRegionHeight() / yCount;
		TextureRegion region = new TextureRegion(src.getTexture(), src.getRegionX() + childWidth * partX,
				src.getRegionY() + childHeight * partY, childWidth, childHeight);
		return region;
	}

	public static Image image(String name, TextureFilter filter) {
		return new Image(region(name, filter));
	}

	public static Image image(String name) {
		return new Image(drawable(name));
	}

	public static Drawable drawable(String name) {
		TextureRegionDrawable drawable = (TextureRegionDrawable) RM.getCachedDrawable(name);
		Texture tex = drawable.getRegion().getTexture();
		if (tex.getMagFilter() != usedTextureFilter || tex.getMinFilter() != usedTextureFilter) {
			tex.setFilter(usedTextureFilter, usedTextureFilter);
		}
		return drawable;
	}

	public static Image createMask() {
		Image img = new Image(RM.getMaskDrawable());
		img.setSize(GM.stage.getWidth(), GM.stage.getHeight());
		return img;
	}

	public static void fullScreenImg(Image img) {
		img.setScaling(Scaling.fill);
		img.setOrigin(Align.center);
		img.setSize(GM.stage.getWidth(), GM.stage.getHeight());
	}

	public static Image createMaskAlphaBlack() {
		Image mask = U.createMask();
		mask.setColor(0, 0, 0, 0.6f);
		return mask;
	}

	public static void setGroupColor(Group group, Color color) {
		for (Actor actor : group.getChildren()) {
			if (actor instanceof Group) {
				setGroupColor((Group) actor, color);
			} else {
				actor.setColor(color);
			}
		}
	}

	public static void setGroupColor(Group group, float r, float g, float b, float a) {
		for (Actor actor : group.getChildren()) {
			if (actor instanceof Group) {
				setGroupColor((Group) actor, r, g, b, a);
			} else {
				actor.setColor(r, g, b, a);
			}
		}
	}

	public static FrameAnimationActor createFrameActor(String regionPath, int xCount, int yCount, int startIndex,
			int endIndex, float delay) {
		TextureRegion region = U.region(regionPath);
		return createFrameActor(region, xCount, yCount, startIndex, endIndex, delay);
	}

	public static FrameAnimationActor createFrameActor(String regionPath, int xCount, int endIndex, float delay) {
		TextureRegion region = U.region(regionPath);
		return createFrameActor(region, xCount, endIndex, delay);
	}

	/**
	 * 取横向的帧序列创建帧动画对象
	 * 
	 * @param region
	 * @param xCount
	 * @param endIndex
	 * @param delay
	 * @return
	 */
	public static FrameAnimationActor createFrameActor(TextureRegion region, int xCount, int endIndex, float delay) {
		return createFrameActor(region, xCount, 1, 0, endIndex, delay);
	}

	/**
	 * 从左下角开始index为0 取相应的帧创建帧动画对象
	 * 
	 * @param region
	 * @param xCount
	 * @param yCount
	 * @param startIndex
	 * @param endIndex
	 * @param delay
	 * @return
	 */
	public static FrameAnimationActor createFrameActor(TextureRegion region, int xCount, int yCount, int startIndex,
			int endIndex, float delay) {
		Array<TextureRegion> list = new Array<TextureRegion>();
		int index = 0;
		for (int y = 0; y < yCount; y++) {
			for (int x = 0; x < xCount; x++) {
				if (index < startIndex) {
					index++;
					continue;
				}
				if (index > endIndex) {
					break;
				}
				list.add(U.regionChild(region, xCount, yCount, x, y));
				index++;
			}
		}
		FrameAnimationActor fa = new FrameAnimationActor();
		fa.init(list, delay);
		return fa;
	}

	/***
	 * 根据 StringUtil.format(picFormat,i) 取单个图片组成序列 [i:startNum...endNum];
	 * @param picFormat
	 * @param startNum 起始序列
	 * @param endNum	结束序列
	 * @param dt
	 * @return
	 */
	public static FrameAnimationActor createFrameActorByFramePics(String picFormat, int startNum, int endNum,
			float dt) {
		Array<TextureRegion> list = new Array<TextureRegion>();
		for (int i = startNum; i < endNum; i++) {
			list.add(U.region(StringUtil.format(picFormat, i)));
		}
		FrameAnimationActor fa = new FrameAnimationActor();
		fa.init(list, dt);
		return fa;
	}

	/**
	 * find index of t in the array.
	 * 
	 * @param t
	 * @param array
	 * @return -1 no this item.
	 */
	public static <T> int indexInArray(T t, T[] array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i] == t) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * find index of val in the array. array[?]==val.
	 * 
	 * @param val
	 * @param array
	 * @return -1 no this item.
	 */
	public static int indexInArray(int val, int[] array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i] == val) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * find index of t in the array. use equal()
	 * 
	 * @param t
	 * @param array
	 * @return -1 no this item.
	 */
	public static <T> int indexInArrayEquals(T t, T[] array) {
		for (int i = 0; i < array.length; i++) {
			if (t.equals(array[i])) {
				return i;
			}
		}
		return -1;
	}

}
